package cn.springseed.common.util;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * ID生成工具。
 * 
 * <p>
 * 设置环境变量：
 * <ul>
 * <li>S8D_WORKER_ID：必须，范围1~32 </li>
 * <li>S8D_DATACENTER_ID：必须，范围1~32 </li>
 * </ul>
 *
 * @author PinWei Wan
 * @since 1.0.0
 */
@Slf4j
public class SnowflakeUtil {
    public final static String PRO_WORKER_ID = "S8D_WORKER_ID";
    public final static String PRO_DATACENTER_ID = "S8D_DATACENTER_ID";
    public final static SnowflakeUtil INSTANCE;

    private final Snowflake snowflake;

    static {
        final String workerIdStr = System.getProperty(PRO_WORKER_ID);
        final String datacenterIdStr = System.getProperty(PRO_DATACENTER_ID); 
        if (StrUtil.isBlank(workerIdStr) || StrUtil.isBlank(datacenterIdStr)) {
            throw new IllegalArgumentException("Environment variable not set: " + PRO_WORKER_ID + ", " + PRO_DATACENTER_ID);
        }

        try {
            Long.valueOf(workerIdStr);
            Long.valueOf(datacenterIdStr);
        } catch(NumberFormatException e) {
            throw new IllegalArgumentException("Environment variable must be number: " + PRO_WORKER_ID + ", " + PRO_DATACENTER_ID, e);
        }

        INSTANCE = new SnowflakeUtil();
    }


    private SnowflakeUtil() {
        final String workerIdStr = System.getProperty(PRO_WORKER_ID);
        final String datacenterIdStr = System.getProperty(PRO_DATACENTER_ID);
        log.info("SnowflakeUtil initialized [workerId={}, datacenterId={}]", workerIdStr, datacenterIdStr);

        snowflake = IdUtil.getSnowflake(Long.valueOf(workerIdStr), Long.valueOf(datacenterIdStr));
        
    }

    public long nextId() {
        return snowflake.nextId();
    }
    
    public String nextIdStr() {
        return snowflake.nextIdStr();
    }

    public long[] nextId(final int size) {
        Assert.isTrue(size > 0, "The value must be greater than zero");

        final long[] ids = new long[size];
        for(int i = 0; i < size; i++) {
            ids[i] = snowflake.nextId();
        }
        return ids;
    }
    
    public String[] nextIdStr(final int size) {
        Assert.isTrue(size > 0, "The value must be greater than zero");

        final String[] ids = new String[size];
        for(int i = 0; i < size; i++) {
            ids[i] = snowflake.nextIdStr();
        }

        return ids;
    }
}
